home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / DDJ0192.ARJ / DIRPICK.C < prev    next >
C/C++ Source or Header  |  1991-09-04  |  9KB  |  330 lines

  1. /****************************************************************
  2.  *                                                              *
  3.  * DIRPICK.C - directory pick routine                           *
  4.  * by Al Williams                                               *
  5.  *                                                              *
  6.  ****************************************************************/
  7. #include <stdio.h>
  8. #include <dos.h>
  9. #include <string.h>
  10. #include <ctype.h>
  11. #include "display.h"
  12.  
  13.  
  14. /* structure to hold directory entries */
  15. struct _dirnames
  16.   {
  17.   char name[13];
  18.   unsigned short attr;
  19.   } dirnames[5][24];
  20.  
  21. /* pointer to null string */
  22. static char *nulls="";
  23.  
  24. /* function to print file names for dirpick */
  25. static void pfname(int cursorx,int cursory)
  26.     {
  27.     writes(dirnames[cursorx][cursory].name);
  28.     if (dirnames[cursorx][cursory].name[0]!='.'
  29.        &&
  30.        dirnames[cursorx][cursory].attr!=(unsigned short) 0xFFFF
  31.        &&
  32.        dirnames[cursorx][cursory].attr&_A_SUBDIR)
  33.       writes("\\");
  34.     }
  35.  
  36.  
  37.  
  38. /* Set drive safely -- returns 0 for success, 1 for error */
  39. safe_setdrive(unsigned drive)
  40.   {
  41.   unsigned olddrive,maxdrive,newdrive;
  42.   struct DOSERROR err;
  43. /* get old drive in case */
  44.   _dos_getdrive(&olddrive);
  45. /* set new drive */
  46.   _dos_setdrive(drive,&maxdrive);
  47. /* did it take? */
  48.   _dos_getdrive(&newdrive);
  49. /* NO: return 1 */
  50.   if (newdrive!=drive) return 1;
  51. /* If, by some chance, there is a file X on the drive
  52.    return success */
  53.   if (!access("X",0)) return 0;
  54. /* If not, see why not */
  55.   dosexterr(&err);
  56. /* If critical error... */
  57.   if (err.exterror==83)
  58.     {
  59. /* reset old drive and fail */
  60.     _dos_setdrive(olddrive,&maxdrive);
  61.     return 1;
  62.     }
  63. /* No critical error -- there just isn't a file
  64.    named X. return success */
  65.   return 0;
  66.   }
  67.  
  68.  
  69. /* MAIN function  -- do a directory on the file spec and
  70.    offer a menu of choices including directories and drives
  71.    maximum of 120 files displayed at once */
  72. char *dirpick(char *spec)
  73.   {
  74. /* set when recursing */
  75.   static int recurse=0;
  76.   int stat=0;
  77.   unsigned nd,nrdrives;
  78.   int x0,y0;
  79.   char *cp,*dirpfx=spec;
  80.   struct find_t info;
  81.   short cursorx=0, cursory=0, x=0, y=0;
  82. /* clear out directory structure */
  83.   memset((void *)dirnames,0,5*24*sizeof(struct _dirnames));
  84. /* check for drive specified */
  85.   if (spec[1]==':')
  86.     {
  87.     unsigned int junk;
  88. /* change to specified drive */
  89. /*    _dos_setdrive(toupper(spec[0])-'A'+1,&junk);
  90.     _dos_getdrive(&junk);
  91.     stat=junk!=toupper(spec[0])-'A'+1; */
  92.     stat=safe_setdrive(toupper(spec[0])-'A'+1);
  93.     dirpfx+=2;
  94.     }
  95. /* see if directory specified */
  96.   if (stat==0 && (cp=strrchr(spec,'\\')))
  97.     {
  98. /* make dirpfx equal to directory. If cp==dirpfx then
  99.    change to root directory */
  100.     *cp='\0';
  101.     stat=chdir(cp==dirpfx?"\\":dirpfx);
  102.     }
  103. /* if stat is non-zero then drive or cd didn't work */
  104.   if (stat) return NULL;
  105. /* chop drive/directory off spec */
  106.   spec=cp?cp+1:dirpfx;
  107.  
  108. /* find first file */
  109.   if (stat=_dos_findfirst(*spec?spec:"*.*",_A_NORMAL|_A_SUBDIR,&info))
  110.      return NULL;
  111. /* save video if not recursive */
  112.   if (!recurse) vidsave();
  113.   color=TEXTCOLOR;
  114. /* clear screen */
  115.   cls();
  116. /* setup psuedo-drives here */
  117.   _dos_getdrive(&nd);
  118.   _dos_setdrive(nd,&nrdrives);
  119.   while (nrdrives--)
  120.     {
  121.     dirnames[cursorx][cursory].name[0]='[';
  122.     dirnames[cursorx][cursory].name[1]=cursory*5+cursorx+'A';
  123.     dirnames[cursorx][cursory].name[2]=']';
  124.     dirnames[cursorx][cursory].name[3]='\0';
  125. /* attribute =0xffff means this is a drive */
  126.     dirnames[cursorx][cursory].attr=0xFFFF;
  127.     goxy(x,y);
  128.     writes(dirnames[cursorx][cursory].name);
  129.     x+=16;
  130.     if (++cursorx==5)
  131.       {
  132.       x=cursorx=0;
  133.       cursory++;
  134.       y++;
  135.       }
  136.     }
  137.   x0=cursorx;
  138.   y0=cursory;
  139. /* while file names are found and screen isn't full */
  140.   while (!stat&&cursory!=24)
  141.     {
  142. /* save name and attribute */
  143.     strcpy(dirnames[cursorx][cursory].name,info.name);
  144.     dirnames[cursorx][cursory].attr=info.attrib;
  145.     goxy(x,y);
  146.     x+=16;
  147.     pfname(cursorx,cursory);
  148.     if (++cursorx==5)
  149.       {
  150.       x=cursorx=0;
  151.       cursory++;
  152.       y++;
  153.       }
  154.     stat=_dos_findnext(&info);
  155.     }
  156. /* found all files... print help line */
  157.   goxy(0,24);
  158.   color=SOCOLOR;
  159.   clreol();
  160.   writes("Use arrows to select. Press <ENTER> to accept"
  161.   " or <ESC> to cancel.");   /* maybe count files not here */
  162.   color=TEXTCOLOR;
  163.  
  164. /* place cursor on first real file (not drive) */
  165.   cursorx=x0;
  166.   cursory=y0;
  167.   x=cursorx*16;
  168.   y=cursory;
  169.  
  170. /* main loop */
  171.   while (1)
  172.     {
  173. /* write file name under cursor */
  174.     color=SOCOLOR;
  175.     goxy(x,y);
  176.     pfname(cursorx,cursory);
  177.     color=TEXTCOLOR;
  178. /* get character */
  179.     stat=getch();
  180.     if (stat=='\r'&&(dirnames[cursorx][cursory].attr&_A_SUBDIR))
  181.       {
  182. /* pressed enter on subdirectory  or drive */
  183.       char *rc;
  184. /* if drive ... */
  185.       if (dirnames[cursorx][cursory].attr==(unsigned short)0xFFFF)
  186.         {
  187.         unsigned int junk;
  188.         char dbg[100];
  189. /*        _dos_setdrive((unsigned)cursory*5+cursorx+1,&junk);
  190.         sprintf(dbg,"junk=%d",junk);
  191.         advise(dbg);
  192.         _dos_getdrive(&junk);
  193.         stat=(junk!=cursory*5+cursorx+1);
  194.         sprintf(dbg,"New drive=%d, stat=%d",junk,stat);
  195.         advise(dbg);                     */
  196.         stat=safe_setdrive((unsigned)cursory*5+cursorx+1);
  197.         }
  198.       else
  199.         stat=chdir(dirnames[cursorx][cursory].name);
  200. /* if dir/drive change was not successful */
  201.       if (stat)
  202.         {
  203.         advise("\aCan't change to that directory");
  204.         continue;
  205.         }
  206. /* recurse */
  207.       recurse++;
  208.       rc=dirpick(spec);
  209. /* restore video */
  210.       if (!recurse) vidrestore();
  211.       recurse--;
  212. /* return file picked */
  213.       return rc;
  214.       }
  215. /* If escape or enter on a file */
  216.     if (stat==27||stat=='\r')
  217.       {
  218. /* restore video
  219.       if (!recurse) vidrestore();
  220. /* return null string (ESC) or file name (ENTER) */
  221.       return stat==27?nulls:dirnames[cursorx][cursory].name;
  222.       }
  223. /* if other normal key, keep going */
  224.     if (stat) continue;
  225. /* get extended scan code */
  226.     stat=getch();
  227. /* reset cursor */
  228.     goxy(x,y);
  229.     pfname(cursorx,cursory);
  230.     switch (stat)
  231.       {
  232. /* up arrow */
  233. case 0x48:
  234.       if (cursory)
  235.         {
  236.         cursory--;
  237.         y--;
  238.         }
  239.       break;
  240.  
  241. /* down arrow */
  242. case 0x50:
  243.       if (cursory!=23&&*dirnames[cursorx][cursory+1].name)
  244.         {
  245.         cursory++;
  246.         y++;
  247.         }
  248.       break;
  249.  
  250. /* left */
  251. case 0x4b:
  252.       if (cursorx)
  253.         {
  254.         cursorx--;
  255.         x-=16;
  256.         }
  257.       break;
  258.  
  259. /* right */
  260. case 0x4d:
  261.       if (cursorx!=4&&*dirnames[cursorx+1][cursory].name)
  262.         {
  263.         cursorx++;
  264.         x+=16;
  265.         }
  266.       break;
  267.       }
  268.     }
  269.   }
  270.  
  271. /**************************************************************
  272.  routines to save and restore the current working drive and
  273.  directory
  274.  **************************************************************/
  275.  
  276. /* saved information */
  277. static unsigned save_drive;
  278. static char save_cd[66];
  279.  
  280. /* save working drive/directory */
  281. void cdsave()
  282.   {
  283.   _dos_getdrive(&save_drive);
  284.   getcwd(save_cd,sizeof(save_cd));
  285.   }
  286.  
  287. /* restore drive/directory */
  288. void cdrestore()
  289.   {
  290.   unsigned junk;
  291.   _dos_setdrive(save_drive,&junk);
  292.   chdir(save_cd);
  293.   }
  294.  
  295. /************************************************************
  296.  prompt for file name -- if file name ends with \ or : or
  297.  contains ? or *, dirpick is called. returns 1 on success
  298.  0 on failure.
  299.  
  300.  If user types in full name, that is passed to the program.
  301.  If he picks name from dirpick, the current drive/directory
  302.  changes as the user picks them. Only the base name of the
  303.  file returns to the caller
  304.  */
  305. int getfilen_at(int x, int y,char *fn,int len)
  306.   {
  307.    if (ask_at(x,y,"File: ",NULL,TEXTCOLOR,len,fn,
  308.               " Enter a file name. Wildcards (?*) are OK."
  309.               " Default=*.*")==-1) return 0;
  310.  
  311. /* if file contains wildcards do dirpick */
  312.    if (*fn=='\0'||strchr(fn,'*')||strchr(fn,'?')||
  313.         fn[strlen(fn)-1]=='\\'||fn[strlen(fn)-1]==':')
  314.      {
  315.      char *pick;
  316.      pick=dirpick(fn);
  317.      if (!pick)
  318.        {
  319.        advise_at(x,y,"No matching files");
  320.        return 0;
  321.        }
  322. /* Escape or bad file */
  323.      if (!*pick) return 0;
  324. /* Fail if file name len exceeds buffer space */
  325.      if (strlen(pick)+1>len) return 0;
  326.      strcpy(fn,pick);
  327.      }
  328.    return 1;
  329.    }
  330.